The well known OS/2 (TM) operating system has been commercially available for a few years and was initially designed as an operating system for personal computers using an Intel 80286 microprocessor. Early versions of OS/2 are considered 16 bit versions in view of the 16 bit architecture of the 80286 microprocessor. Current and future versions of OS/2 are considered 32 bit versions in view of the 32 bit architecture in microprocessors such as the 80386 and 80486. While an operating system is a collection of programs that provide many different functions, the general function to which the invention pertains is that of task management and, more specifically, exception management. The OS/2 operating system can operate the microprocessor in a protected mode to provide multitasking. Such system thus allows more than one program to be concurrently run. The general function of task management is to allocate resources to the different programs so that the various programs can be concurrently run in different time slices. Under OS/2, application programs are part of "threads" and "processes".
A process is an entity which owns system resources assigned to the process and includes at least one thread of execution. A thread is a dispatchable unit of work or string of instructions to be executed. A process can have more than one thread and in such case is considered "multithreaded". A concurrent application can be created as distinct processes or as multiple threads in a single process. Thread code is written in reentrant form so that the same code can be used concurrently in plural threads. In the latter case, each thread has access to the system resources owned by the process which includes the thread. In contrast, other operating systems allowing multitasking but each task is in reality a single process having a single thread.
Multiple threads in a process execute asynchronously of each other and as this happens, an "exception" may occur in one or more threads, and such action creates the problem which the invention overcomes as described in more detail below. An "exception" is a hardware related error or event that occurs during execution of instructions. The operating system is notified by the processor when the exception occurs, allowing an exception management function to "handle" the exception. The handler may be either a system handler or a user defined handler dependent on the type of exception. A system handler automatically handles certain exceptions over which the user has no control. For other exceptions, the user or application may define an exception handler which the user can optionally invoke through exception registration. If the user does not provide a user defined handler or invoke one properly, the system will automatically apply default actions. Heretofore, 16 bit OS/2 allows a user or programmer to define handlers for the following exceptions: a divide by 0 fault, an overflow trap, a bounds check fault, an invalid opcode fault, and a processor extension not present fault. By writing the handlers in reentrant form, plural copies of the same handler can be used.
Exception handling in 16 bit OS/2 is managed on a per process basis and this has created problems which the present invention improves upon and overcomes. Each thread registers an exception handler by using an application programming interface (API) call and this causes an entry to be made in the exception vector of the kernel per process data area. The exception vector is common to all threads within the process and contains a table of pointers to handlers that have been registered. The pointers are stored in the table in accordance with the type of exception. Each thread has access to all pointers or table entries. This creates a problem in the situation where a first thread registers its own handler for a given type of exception and subsequently a second thread registers its own handler for the same type whereby the first pointer is overwritten. Should the exception occur while the first thread is executing, the second handler will be executed without informing the first handler that it is not the one originally registered. In other words, the threads have access to the table and can unknowingly corrupt access to handlers of other threads sharing the exception vector.
A second problem can occur when a first thread has requested from a subsystem a transaction that must complete. For example, a thread might request data from a remote data base subsystem. Suppose then that a second thread is executing and causes an abnormal termination to occur. Such exceptions are handled on a per process basis, and the whole process is terminated without notifying individual threads and allowing them a chance to terminate gracefully. In the example cited, the thread in the remote data base system never gets a chance to roll back its transaction, potentially causing integrity problems in the remote data base.